class Magnifier
{
    constructor(el,options = {})
    {
        this.el = document.querySelector(el)
        this.imgObj = this.el.querySelector('.img')
        this.maskObj = this.el.querySelector('.mask')
        this.enlargeObj = this.el.querySelector('.enlarge')
        this.init()
    }

    init() {
        this.overOut()                 // 鼠标移入移出
        this.enlargeWH()               // 计算enlarge盒模型的宽度和高度
        this.maskMove()                // 遮罩框和鼠标同步移动
        // this.enlargeMove()          // 同步放大镜效果框移动,同步放大镜移动的时候调用即可，这里不用调用
        this.smallChange()             // 小图切换
    }

    overOut() {
        // 步骤：
        // 1、获取【放大镜盒模型】左侧的图片，并绑定鼠标移入、移出事件
        // 2、事件处理函数中---显示、隐藏遮罩框和放大镜效果框
        this.imgObj.onmouseover = () => this.maskObj.style.display = this.enlargeObj.style.display = 'block'
        this.imgObj.onmouseout = () => this.maskObj.style.display = this.enlargeObj.style.display = 'none'
    }

    getStyle(tagObj,cssAttr){
        // return window.getComputedStyle ? window.getComputedStyle(标签对象).css属性名 : 标签对象.currentStyle.css属性名
        // return window.getComputedStyle ? window.getComputedStyle(tagObj).cssAttr : tagObj.currentStyle.cssAttr      // 注意：当对象的键是变量的时候，不是用点语法，是用数组中括号语法
        return window.getComputedStyle ? window.getComputedStyle(tagObj)[cssAttr] : tagObj.currentStyle[cssAttr]      // 注意：当对象的键是变量的时候，不是用点语法，是用数组中括号语法
    }

    enlargeWH() {
        /*盒子比例:
        目的：让放大镜显示的内容  和  遮罩框黄色  一样
        公式：      div.enlarge background          div.enlarge w
                    ---------------------    =      -----------
                    div.img background               div.mask w
        计算：div.enlarge w = div.mask w * (div.enlarge background / div.img background )
        */
       /*
       知识点1：获取图片的offsetLeft必须等图片加载完毕，也就是imgObj.onload
       知识点2：offset系列/client系列必须是可见元素，也就是 display：block; ，不能是none
       解决方法1：给元素设置 visibility:hidden; 透明属性,就可以用它的offset和client
       解决方法2：获取非行内样式的宽高
       */

        // 一、获取mask盒模型的宽度高度，需要用非行内样式获取
        // let maskW = this.getStyle(this.maskObj,width)    // 这种情况下获取的宽度是带px的,需要用parseInt取整,并且getStyle也是公共空间上的方法，需要用this调用
       let maskW = parseInt(this.getStyle(this.maskObj,'width')) 
       let maskH = parseInt(this.getStyle(this.maskObj,'height')) 


        // 二、获取enlarge盒模型背景图片的宽度高度，也需要用非行内样式获取
        // let enlargeBgSize = this.getStyle(this.enlargeObj,'background-size')     // background-size有宽度和高度两个数值，所以获取之后是一个字符串，所以需要把字符串转化成数组，然后分别获取宽度和高度
        let enlargeBgSize = (this.getStyle(this.enlargeObj,'background-size')).split(' ')    // 上面的字符串打出来是'800px 800px'   所以转成数组需要用空格分开
        let enlargeBgW = parseInt(enlargeBgSize[0])          // 获取数组的第一个值为宽度
        let enlargeBgH = parseInt(enlargeBgSize[1])          // 获取数组的第一个值为高度


        // 三、获取img盒模型的背景图片的宽度高度【或者直接获取img盒模型的宽度高度，因为img背景大小和盒模型的宽高一样】，也需要用非行内样式获取
        let imgW = parseInt(this.getStyle(this.imgObj,'width'))
        let imgH = parseInt(this.getStyle(this.imgObj,'height'))


        // 四、计算enlarge盒模型的宽度和高度
        let enlargeW = maskW * (enlargeBgW / imgW )
        let enlargeH = maskH * (enlargeBgH / imgH )
        this.enlargeObj.style.width = enlargeW + 'px'
        this.enlargeObj.style.height = enlargeH + 'px'
    }

    maskMove() {
        // 步骤；
        // 1、获取img盒模型，绑定鼠标移动事件
        this.imgObj.onmousemove = (evt) => {
            // 2、事件处理函数中---获取事件对象
            let e = evt || window.event
            // 3、事件处理函数中---获取鼠标位置【在遮罩框的中间】
            let x = e.pageX - this.el.offsetLeft - this.maskObj.offsetWidth/2
            let y = e.pageY - this.el.offsetTop - this.maskObj.offsetHeight/2
            // 4、事件处理函数中---限制遮罩框最大的可移动范围
            if(x<0) x=0
            if(y<0) y=0
            let maxX = this.imgObj.clientWidth - this.maskObj.offsetWidth
            let maxY = this.imgObj.clientHeight - this.maskObj.offsetHeight
            if(x>maxX) x=maxX
            if(y>maxY) y=maxY
            // 5、事件处理函数中---同步遮罩框和鼠标一起移动
            this.maskObj.style.left = x + 'px'
            this.maskObj.style.top = y + 'px'
            // 6、同步放大镜效果框移动
            this.enlargeMove(x,y)
        }
    }

    enlargeMove(x,y) {
        // 右侧背景图片的移动 = mask的left * ( 右侧enlarge盒模型的宽度 / 左侧mask盒模型的宽度 )     // 右侧enlarge的宽度 / 左侧mask的宽度  是之前算的比例
    
        // 或者

        // 右侧背景图片的移动 = mask的left * ( 右侧背景图片的宽度 / 左侧背景图片的宽度 )
        // 1、右侧背景图片的宽度：
        let enlargeBgSize = (this.getStyle(this.enlargeObj,'background-size')).split(' ')    // 上面的字符串打出来是'800px 800px'   所以转成数组需要用空格分开
        let enlargeBgW = parseInt(enlargeBgSize[0])          // 获取数组的第一个值为宽度
        let enlargeBgH = parseInt(enlargeBgSize[1])          // 获取数组的第一个值为高度

        // 2、左侧背景图片的宽度
        let imgW = parseInt(this.getStyle(this.imgObj,'width'))
        let imgH = parseInt(this.getStyle(this.imgObj,'height'))

        // 3、右侧背景图片的移动
        let leftX = x * ( enlargeBgW / imgW )
        let topY = y * ( enlargeBgH / imgH )
        this.enlargeObj.style.backgroundPosition = `-${leftX}px -${topY}px`
    }

    smallChange() {
        // 小图切换步骤：
        // 1、获取ul li下的小图片img
        let liObjs = this.el.querySelectorAll('ul li')
        // 2、遍历
        liObjs.forEach((item,i) => {
            // 3、挨个绑定点击事件
            item.onclick = () => {
                // 4、移出目前所有的class，并且给当前点击的加class
                this.el.querySelector('ul li.active').className = ''
                item.className = 'active'
                // 5、事件处理函数中---同步img盒模型的背景切换
                this.imgObj.style.backgroundImage = `url(./img/${i+1}.jpg) `
                // 6、事件处理函数中---同步enlarge盒模型的背景切换
                this.enlargeObj.style.backgroundImage = `url(./img/big${i+1}.jpg)`
                // 7、同步放大镜效果框移动
                this.enlargeMove(x,y)
            }
        }) 
    }

}
export default Magnifier 